<template>
  <a-row :gutter="gutter" wrap>
    <a-form
      ref="tableForm"
      class="table-form"
      :model="formModel"
      auto-label-width
      :layout="layout"
      @submit="handleSubmit"
      :disabled="disabled"
    >
      <a-col
        v-for="(field, index) in visibleFields"
        :key="field.name"
        :data-index="field.index"
        :span="field.fieldProps.span ? field.fieldProps.span : 24"
        :class="{
          isDisplay: table && !collasp && index > 1,
        }"
      >
        <a-form-item
          :field="field.name"
          :label="field.label"
          :rules="field.rules"
          :tooltip="field.tooltip"
          :key="field.name + index"
        >
          <component
            v-if="field.type !== 'SelectIcon' && field.type !== 'a-upload'"
            :is="field.type ? field.type : 'a-input'"
            v-model="formModel[field.name]"
            v-bind="field?.fieldProps"
            :placeholder="
              getPlaceholder(field.fieldProps.placeholder, field.type)
            "
            @change="change"
          >
            <template v-if="field.type === 'a-select'">
              <template v-if="field.slotName === 'status'">
                <a-option
                  v-for="option in field.selectOptions"
                  :key="option.value"
                  :value="option.value"
                >
                  <a-badge :status="option.status" :text="option.label" />
                </a-option>
              </template>
              <template v-else>
                <a-option
                  v-for="(item, index) in field.selectOptions"
                  :key="index"
                  :value="
                    item[
                      field?.fieldProps?.fieldNames?.value
                        ? field?.fieldProps?.fieldNames?.value
                        : 'value'
                    ]
                  "
                >
                  {{
                    item[
                      field?.fieldProps?.fieldNames?.label
                        ? field?.fieldProps?.fieldNames?.label
                        : 'label'
                    ]
                  }}
                </a-option>
              </template>
            </template>
            <template
              v-if="field.checkboxOptions && field.type === 'a-checkbox-group'"
            >
              <a-checkbox
                v-for="item in field.checkboxOptions"
                :value="item.value"
                :key="item.label + index"
              >
                {{ item.label }}
              </a-checkbox>
            </template>
            <template v-if="field.type === 'a-radio-group'">
              <a-radio
                v-for="(item, index) in field.options"
                :key="item.label + index"
                :value="item.value"
                >{{ item.label }}</a-radio
              >
            </template>
          </component>

          <!--     文件附件上传     -->
          <a-upload
            key="upload1"
            v-model:file-list="formModel[field.name]"
            v-if="field.type === 'a-upload' && field?.slotName !== 'images'"
            :custom-request="customRequest"
            :multiple="field.fieldProps.multiple || false"
            accept="*"
            :limit="field.fieldProps.limit"
            :max-count="field.fieldProps.maxCount || 1"
          />
          <a-upload
            key="upload2"
            v-if="field.type === 'a-upload' && field?.slotName === 'images'"
            list-type="picture-card"
            :limit="field.fieldProps.limit"
            v-model:file-list="formModel[field.name]"
            tip="上传"
            accept="*"
            :custom-request="customRequestImage"
            :max-count="field.fieldProps.maxCount || 1"
            image-preview
          />
          <select-icon
            v-if="field.type === 'SelectIcon'"
            v-model:value="formModel[field.name]"
            :fieldProps="field.fieldProps"
            :placeholder="field.placeholder"
            @change="change"
          ></select-icon>
          <template #extra>
            <div>{{ field.extra }}</div>
          </template>
        </a-form-item>
      </a-col>
      <a-col
        :span="8"
        flex="1"
        style="text-align: right; margin-bottom: 20px; grid-column: 3 / span 1"
        v-if="table"
      >
        <a-button style="margin-right: 10px" @click="resetForm1">
          重置
        </a-button>
        <a-button
          html-type="submit"
          type="primary"
          :loading="loading"
          :disabled="isFormChanged"
        >
          查询
        </a-button>
        <span v-if="visibleFields.length > 2">
          <a-link
            v-if="!collasp"
            :hoverable="false"
            style="margin-left: 10px"
            @click="
              () => {
                collasp = true;
              }
            "
            >展开<icon-down style="margin-left: 10px"
          /></a-link>
          <a-link
            @click="
              () => {
                collasp = false;
              }
            "
            v-if="collasp"
            :hoverable="false"
            style="margin-left: 10px"
            >收缩<icon-up style="margin-left: 10px"
          /></a-link>
        </span>
      </a-col>
      <!--    普通表单  -->
      <a-form-item v-if="!table && showSubmit && !hiddenBtn">
        <a-button
          :loading="loading"
          type="primary"
          html-type="submit"
          :disabled="isFormChanged"
          >{{ btnTitle[0] }}</a-button
        >
        <a-button style="margin-left: 10px !important" @click="resetForm">
          {{ btnTitle[1] ? btnTitle[1] : '重置' }}
        </a-button>
      </a-form-item>
    </a-form>
  </a-row>
</template>

<script lang="ts" setup>
  import { toRefs, ref, watch, computed, nextTick } from 'vue';
  import { FormInstance, Message } from '@arco-design/web-vue';
  import { isEqual, cloneDeep } from 'lodash';
  import axios from 'axios';
  import { upload } from '@/api/global';
  import { getToken } from '@/utils/auth';
  import { deepClone } from '@arco-vue-pro-components/pro-components/es/pro-table/utils';

  defineOptions({
    name: 'ProForm',
  });
  const collasp = ref(false);
  const originalFormModel = ref({});
  const isFormChanged = ref(false);

  const props = withDefaults(
    defineProps<{
      formJson: Record<string, any>[];
      formData: any;
      layout?: 'horizontal' | 'vertical' | 'inline';
      labelAlign?: 'left' | 'right';
      gutter?: number;
      display?: boolean;
      table?: boolean;
      showSubmit?: boolean;
      loading?: boolean;
      btnTitle?: string[];
      hiddenBtn?: boolean;
      disabled?: boolean;
    }>(),
    {
      loading: false,
      gutter: 20,
      layout: 'horizontal',
      formJson: () => [],
      display: false,
      rules: () => [],
      formData: () => ({}),
      table: false,
      showSubmit: true,
      btnTitle: () => ['保存', '重置'],
      hiddenBtn: false,
      disabled: false,
    }
  );

  const emit = defineEmits([
    'update:loadingBtn',
    'search',
    'change',
    'resetForm',
    'formModelChange',
  ]);

  function resetForm1() {
    tableForm.value?.resetFields();
    emit('resetForm');
  }

  // 获取默认值
  function getPlaceholder(placeholder, type) {
    if (type === 'a-range-picker') {
      return '';
    } else {
      return placeholder ? placeholder : '请输入';
    }
  }

  const tableForm = ref<FormInstance | null>(null);
  const formModel = ref({} as any);
  const { formJson, formData, layout, labelAlign, gutter } = toRefs(props);

  const checkForm = async () => {
    return await tableForm.value?.validate();
  };

  const visibleFields = computed(() => {
    if (!props.display) {
      return formJson?.value === undefined ? [] : formJson.value;
    }
    return props?.display() || [];
  }) as unknown as Array<any>;

  // 初始化原始数据
  watch(
    () => props.formData,
    (newVal) => {
      formModel.value = cloneDeep(newVal);
      originalFormModel.value = cloneDeep(newVal); // 同步更新原始数据
      isFormChanged.value = true;
    },
    { immediate: true, deep: true }
  );

  watch(
    () => formModel.value,
    (newVal, oldVal) => {
      isFormChanged.value = isEqual(formModel.value, originalFormModel.value);
      emit('formModelChange', newVal, oldVal);
    },
    { deep: true }
  );

  nextTick(() => {
    const elements = document.querySelectorAll('.table-form .arco-col');
    const formBox = document.querySelector('.table-form');
    const elementsArray = Array.from(elements);
    elementsArray.sort((a, b) => {
      const indexA = a.getAttribute('data-index');
      const indexB = b.getAttribute('data-index');
      return parseInt(indexA || '0') - parseInt(indexB || '0');
    });
    elementsArray.forEach((element) => {
      if (!element.getAttribute('data-index')) return;
      formBox?.appendChild(element);
    });
  });

  const change = (val: any) => {
    emit('change', val);
  };

  // 文件附件上传
  const customRequest = async (option: any) => {
    const { onProgress, onError, onSuccess, fileItem, name } = option;
    const formData = new FormData();
    let connectName = undefined;
    formJson.value.forEach((item: any) => {
      if (item.type === 'a-upload') {
        connectName = item.fieldProps?.connectionName;
      }
    });
    formData.append(name || 'file', fileItem.file);
    const url = import.meta.env.VITE_API_BASE_URL + 'global/upload';
    try {
      3;
      const res = await axios.post(url, formData, {
        headers: {
          'Content-Type': 'multipart/form-data',
          'Token': getToken(),
        },
        onUploadProgress: (progressEvent) => {
          const percentCompleted = Math.round(
            (progressEvent.loaded * 100) / progressEvent.total
          );
          onProgress({ percent: percentCompleted });
        },
      });
      // 如果关联信息存在
      onSuccess(res.data);
      if (!!connectName) {
        formModel.value[connectName] = deepClone(fileItem.name);
      }
    } catch (error) {
      onError(error, fileItem.file);
    }
  };
  // 图片附件上传
  const customRequestImage = async (option: any) => {
    const { onProgress, onError, onSuccess, fileItem, name } = option;
    const formData = new FormData();
    let connectName = undefined;
    formJson.value.forEach((item: any) => {
      if (item.type === 'a-upload') {
        connectName = item.fieldProps?.connectionName;
      }
    });
    formData.append(name || 'file', fileItem.file);
    const url = import.meta.env.VITE_API_BASE_URL + 'global/upload';
    try {
      const res = await axios.post(url, formData, {
        headers: {
          'Content-Type': 'multipart/form-data',
          'Token': getToken(),
        },
        onUploadProgress: (progressEvent) => {
          const percentCompleted = Math.round(
            (progressEvent.loaded * 100) / progressEvent.total
          );
          onProgress({ percent: percentCompleted });
        },
      });
      // 如果关联信息存在
      onSuccess(res.data);
      if (!!connectName) {
        formModel.value[connectName] = deepClone(fileItem.name);
      }
    } catch (error) {
      onError(error, fileItem.file);
    }
  };

  const handleSubmit = async ({ values, errors }) => {
    if (errors || isFormChanged.value) return false;

    const formData = new FormData();

    // 遍历所有表单字段
    Object.entries(formModel.value).forEach(([key, value]) => {
      formData.append(key, JSON.stringify(value));

      // if (key.includes('upload')) {
      //   // 识别上传字段
      //   // 使用统一的参数名 "files" 上传所有文件
      //   value.forEach((file: any) => {
      //     formData.append('files', file.originFileObj); // 参数名改为 files
      //   });
      // } else {
      //   formData.append(key, JSON.stringify(value));
      // }
    });

    if (props.table) {
      emit('update:loadingBtn', true);
      try {
        await emit('search', cloneDeep(formModel.value));
        // await axios.post('/api/upload', formData, {
        //   headers: { 'Content-Type': 'multipart/form-data' },
        // });
      } catch (error) {
        Message.error('文件上传失败');
      } finally {
        emit('update:loadingBtn', false);
      }
    } else {
      await emit('search', cloneDeep(formModel.value));
    }
  };

  const resetForm = () => {
    tableForm.value?.resetFields();
    formModel.value = cloneDeep(originalFormModel.value);
    isFormChanged.value = false;
  };

  const setFormItm = (name: String, value: any) => {
    formModel.value[name] = value;
  };

  defineExpose({
    formModel,
    tableForm,
    checkForm,
    setFormItm,
  });
</script>

<style scoped lang="less">
  .arco-btn {
    width: 80px;
  }
  .arco-col {
  }

  .arco-form {
    flex-direction: row !important;
    flex-wrap: wrap;
  }
  :deep(.arco-upload-wrapper) {
    width: auto; // 修改宽度设置
  }
  .isDisplay {
    display: none;
  }
  :deep(.icon) {
    width: 1.2em !important;
    height: 1.2em !important;
  }

  /* 新增上传样式 */
  .upload-list {
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    width: 100%;
    display: flex;
    flex-direction: column;
    margin-top: -10px;
  }

  .upload-list-item {
    padding: 5px;
    border-radius: 4px;
    display: flex;
    margin-bottom: 5px;
    align-items: center;
    justify-content: space-between;
    background: #f7f8fa;
  }

  .upload-preview {
    display: flex;
    flex-direction: row;
    align-items: center;
  }

  .upload-preview img {
    max-width: 100%;
    height: 40px;
    object-fit: cover;
  }

  .upload-operations {
    display: flex;
    gap: 10px;
  }

  .custom-upload-avatar {
    cursor: pointer;
  }
</style>
